// 
// SoapTrace.Net - A soap message monitoring utility. 
// 
// Copyright (C) 2004 Matthew Ward
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// 
// Matthew Ward (mrward@users.sourceforge.net)
// 

using System;
using System.Text;

namespace SoapTrace.Core.Communication
{
	/// <summary>
	/// A dynamically resizing array of bytes.
	/// </summary>
	public class ByteArray
	{
		/// <summary>
		/// The array of bytes.
		/// </summary>
		private byte[ ] m_Bytes = new byte[ 1024 ];

		/// <summary>
		/// The number of bytes added to the array.
		/// </summary>
		private int m_BytesAdded;

		/// <summary>
		/// The size the array will increase if it needs to expand.
		/// </summary>
		private int m_SizeIncrease = 1024;

		/// <summary>
		/// Creates a new instance of the <see cref="ByteArray"/>
		/// class.
		/// </summary>
		public ByteArray( )
		{
		}

		/// <summary>
		/// Gets a byte array.
		/// </summary>
		/// <returns>A byte array.</returns>
		public byte[ ] GetBytes( )
		{
			byte[ ] Bytes = new byte[ m_BytesAdded ];

			for( int i = 0; i < m_BytesAdded; ++i )
			{
				Bytes[ i ] = m_Bytes[ i ];
			}

			return Bytes;
		}

		/// <summary>
		/// Gets the byte at the specified index.
		/// </summary>
		public byte this[ int index ]
		{
			get
			{
				return m_Bytes[ index ];
			}
		}

		/// <summary>
		/// Appends a byte to the end of the array.
		/// </summary>
		/// <param name="dataByte">The byte to add to the array.</param>
		public void Add( byte dataByte )
		{
			m_Bytes[ m_BytesAdded ] = dataByte;
			++m_BytesAdded;

			if( m_BytesAdded >= m_Bytes.Length )
			{
				int NewSize = m_Bytes.Length + m_SizeIncrease;

				byte[ ] NewBytes = new byte[ NewSize ];

				m_Bytes.CopyTo( NewBytes, 0 );
				m_Bytes = NewBytes;
			}
		}

		/// <summary>
		/// Appends an array of bytes to the end of the byte array.
		/// </summary>
		/// <param name="bytes">An array of bytes to add.</param>
		/// <param name="length">The number of bytes in the array to add.</param>
		public void Add( byte[ ] bytes, int length )
		{
			for( int i = 0; i < length; ++i )
			{
				Add( bytes[ i ] );
			}
		}

		/// <summary>
		/// Appends the items of one <see cref="ByteArray"/> to 
		/// another.
		/// </summary>
		/// <param name="array">A <see cref="ByteArray"/> to append to this 
		/// one.</param>
		public void Add( ByteArray array )
		{
			for( int i = 0; i < array.Length; ++i )
			{
				Add( array[ i ] );
			}
		}

		/// <summary>
		/// Gets the number of bytes in this byte array.
		/// </summary>
		public int Length
		{
			get
			{
				return m_BytesAdded;
			}
		}

		/// <summary>
		/// Removes all the bytes in this byte array.
		/// </summary>
		public void Clear( )
		{
			m_BytesAdded = 0;
		}

		/// <summary>
		/// Shifts the bytes left the specified number of times.
		/// </summary>
		/// <param name="amount">The number of times to shift the bytes.</param>
		public void ShiftLeft( int amount )
		{
			if( amount >= m_BytesAdded )
			{
				Clear( );
			}
			else
			{
				for( int i = 0; i < amount; ++i )
				{
					m_Bytes[ i ] = m_Bytes[ i + amount ];
				}

				m_BytesAdded -= amount;
			}
		}

		/// <summary>
		/// Gets a UTF8 string version of the byte array.
		/// </summary>
		/// <returns></returns>
		public string GetUTF8String( )
		{
			return UnicodeEncoding.UTF8.GetString( m_Bytes, 
				0, 
				m_BytesAdded );
		}

	}
}
